<!-- 数字输入框 -->
<template>
	<u-input
		ref="input"
		:type="typeCom || 'number'"
		:value="inputVal"
		:modelValue="inputVal"
		:placeholder="placeholder"
		:clearable="clearable"
		:disabled="disabled"
		:height="height"
		:input-align="inputAlign"
		:placeholder-style="placeholderStyle"
		:confirm-type="confirmType"
		:custom-style="customStyle"
		:focus="focus"
		:border="border"
		:cursor-spacing="cursorSpacing"
		:selection-start="selectionStart"
		:selection-end="selectionEnd"
		:trim="trim"
		@input="onInput"
		@focus="onFocus"
		@blur="onBlur"
		@confirm="onConfirm"
		@clear="onClear"
	></u-input>
</template>

<script>
	export default {
		name: "vk-data-input-number",
		emits: ["update:modelValue", "input", "blur", "focus", "confirm", "clear", "change"],
		props: {
			// 值
			value: {},
			modelValue: {},
			// 输入框的类型，number，money，percentage，discount
			type: {
				type: String,
				default: "number"
			},
			// 提示
			placeholder: {
				type: String,
				default: ""
			},
			// 小数点位数
			precision: {
				type: [String, Number],
				default: 2
			},
			max: {
				type: [String, Number]
			},
			min: {
				type: [String, Number]
			},
			disabled: {
				type: Boolean
			},
			clearable: {
				type: [Boolean, String]
			},

			// 输入框文字的对齐方式
			inputAlign: {
				type: String
			},
			// 高度，单位rpx
			height: {
				type: [String, Number]
			},
			placeholderStyle: {
				type: String,
				default: "color:#c0c4cc"
			},
			confirmType: {
				type: String,
				default: "done"
			},
			customStyle: {
				type: Object
			},
			// 是否显示边框
			border: {
				type: Boolean,
				default: false
			},
			borderColor: {
				type: String,
				default: "#dcdfe6"
			},
			cursorSpacing: {
				type: [Number, String],
				default: 0
			},
			selectionStart: {
				type: [Number, String]
			},
			selectionEnd: {
				type: [Number, String]
			},
			trim: {
				type: Boolean,
				default: true
			},
			// 是否自动获得焦点
			focus: {
				type: Boolean,
				default: false
			}
		},
		data: function() {
			// 组件创建时，进行数据初始化
			return {
				inputVal: ""
			};
		},
		mounted() {
			this.init();
		},
		methods: {
			// 初始化
			init() {},
			// 更新表单值
			_updateValue(value) {
				this.$emit("input", value);
				this.$emit("update:modelValue", value);
				this.$emit("change", value);
			},
			// 数字 value 转 字符串inputVal
			valueToInputVal(value) {
				let vk = uni.vk;
				let { precision, type } = this;
				if (isNaN(value) || vk.pubfn.isNull(value)) return "";
				if (typeof value == "string") {
					value = Number(value);
					this._updateValue(value);
				}
				let inputVal = "";
				if (type === "money") {
					inputVal = parseFloat((value / 100).toFixed(Number(precision)));
				} else if (type === "percentage") {
					inputVal = parseFloat((value * 100).toFixed(Number(precision) + 2));
				} else if (type === "discount") {
					inputVal = parseFloat((value * 10).toFixed(Number(precision) + 1));
				} else {
					inputVal = value.toString();
				}
				return inputVal;
			},
			// 字符串inputVal 转 数字 value
			inputValToValue(inputVal) {
				let vk = uni.vk;
				let { type, precision } = this;
				let value = "";
				if (vk.pubfn.isNotNull(inputVal)) {
					value = Number(inputVal);
					// 此处必须做四舍五入取整,否则会出现精度不准确。
					if (type === "money") {
						value = Math.round(value * 100);
					} else if (type === "percentage") {
						value = parseFloat((value / 100).toFixed(Number(precision) + 2));
					} else if (type === "discount") {
						value = parseFloat((value / 10).toFixed(Number(precision) + 1));
					}
				}
				return value;
			},
			// 监听 - 获得焦点
			onFocus() {
				this.$emit("focus", this.valueCom);
			},
			// 监听 - 失去焦点
			onBlur() {
				let vk = uni.vk;
				//在失去焦点时,将值转数字
				let { inputVal, min } = this;
				let value = "";
				if (vk.pubfn.isNotNull(inputVal)) {
					// 判断最小值
					if (vk.pubfn.isNotNull(min) && parseFloat(inputVal) < parseFloat(min)) {
						inputVal = min + "";
					}
					value = this.inputValToValue(inputVal);
					this._updateValue(value);
				}
				this.$emit("blur", value);
			},
			// 监听 - 输入
			onInput(inputVal) {
				this.inputVal = inputVal;
				this.$nextTick(() => {
					inputVal = this.inputValFilter(inputVal);
					this.inputVal = inputVal;
					let value = this.inputValToValue(inputVal);
					this._updateValue(value);
				});
			},
			// 监听 - 回车
			onConfirm() {
				this.onBlur();
				this.$emit("confirm", this.valueCom);
			},
			// 监听 - 清除
			onClear() {
				this._updateValue("");
				this.$emit("clear", "");
			},
			// 数据过滤
			inputValFilter(inputVal) {
				let vk = uni.vk;
				let { precision, maxCom: max } = this;
				inputVal = inputVal.toString();
				inputVal = inputVal.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
				if (Number(precision) == 0) {
					let n1 = inputVal.indexOf(".");
					if (n1 > -1) {
						inputVal = inputVal.substring(0, n1);
					}
				} else if (Number(precision) > 0) {
					inputVal = inputVal.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的
					inputVal = inputVal
						.replace(".", "$#$")
						.replace(/\./g, "")
						.replace("$#$", ".");
					let n2 = inputVal.lastIndexOf(".");
					let n1 = inputVal.indexOf(".");
					if (n1 > -1 && n1 + 1 + Number(precision) <= inputVal.length) {
						inputVal = inputVal.substring(0, n1 + 1 + Number(precision));
					}
				}
				//最大值判断
				if (vk.pubfn.isNotNull(max) && parseFloat(inputVal) > parseFloat(max)) {
					inputVal = max + "";
				}
				return inputVal;
			}
		},
		watch: {
			valueCom: {
				immediate: true,
				handler: function(newVal) {
					this.inputVal = this.valueToInputVal(newVal);
				}
			}
		},
		// 计算属性
		computed: {
			valueCom() {
				// #ifdef VUE2
				return this.value;
				// #endif

				// #ifdef VUE3
				return this.modelValue;
				// #endif
			},
			maxCom() {
				let vk = uni.vk;
				let { type, max } = this;
				if (vk.pubfn.isNotNull(max)) {
					return max;
				}
				if (type === "money") {
					return 1000000000000;
				} else if (type === "percentage") {
					return 100;
				} else if (type === "discount") {
					return 10;
				} else {
					return 1000000000000;
				}
			},
			typeCom() {
				let type = this.precision ? 'digit' : 'number';
				// #ifdef VUE3
				// #ifdef H5
				// vue3 h5端, digit 无法输入小数点, 所以使用 text
				if (type === "digit") {
					type = "text";
				}
				// #endif
				// #endif
				return type;
			}
		}
	};
</script>

<style lang="scss" scoped></style>